import axios from "axios";
import qs from "qs"
import type { AxiosInstance } from "axios";
import { ILoginResult } from '../login/type'
import { IDataType } from '../types';
import type { InterceptorsHooks, RequestConfig } from "./type";
import { resolve } from "path";

class Request {
  instance: AxiosInstance;
  interceptors?: InterceptorsHooks;
  // 当前是否正在进行刷新token操作
  isNotRefreshing: Boolean;
  // 保存请求队列
  requests: Array<any>;
  constructor(config: RequestConfig) {
    this.isNotRefreshing = true
    this.requests = []
    this.instance = axios.create(config)
    this.interceptors = config.interceptors
    this.instance.interceptors.request.use(
      this.interceptors?.requestInterceptors,
      this.interceptors?.requestInterceptorsCatch
    )
    this.instance.interceptors.response.use(
      this.interceptors?.requestInterceptors,
      this.interceptors?.requestInterceptorsCatch
    )
    this.instance.interceptors.request.use(
      (config) => {
        console.log('所有实例的拦截器');
        return config
      },
      (err) => {
        return err;
      }
    )
    this.instance.interceptors.response.use(
      async (res) => {
        if (res.data.status === 10415) {
          // 保存一个config，重发请求使用
          const config = res.config;
          // 用户选择记住账号密码，存储在localStorage中。没有选择记住的直接让她重新登录。在路由拦截中做，不在此操作
          const username = localStorage.getItem('username')
          const password = localStorage.getItem('password')
          const account = qs.stringify({
            username,
            password
          })
          if (this.isNotRefreshing) {
            this.isNotRefreshing = false
            return this.post<IDataType<ILoginResult>>({
              url: 'api/login',
              headers: {
                'content-type': 'application/x-www-form-urlencoded'
              },
              data: account
            }).then(res => {
              if (res.data.status === 200) {
                // 刷新成功，保存新的token
                localStorage.setItem('token', res.data.token)
                //执行requests队列中的请求，（requests中存的不是请求参数，而是请求的Promise函数，这里直接拿来执行就好）
                this.requests.forEach(run => run())
                this.requests = []
                return this.instance(config);
              } else {
                // 登录又失败，直接让用户去重新登录
                localStorage.removeItem("token")
              }
            }).catch(() => {
              localStorage.removeItem("token")
            }).finally(() => {
              this.isNotRefreshing = true;
            })
          } else {
            // 将并发的其他接口保存在请求队列中，在登录接口成功的回调中去执行
            return new Promise(resolve => {
              console.log(11111);
              this.requests.push(() => {
                resolve(this.instance.request(config))
              })
            })
          }
        }
        console.log('所有实例都有的响应拦截器', res);
        return res
      },
      (err) => {
        return err
      }
    )
  }
  api<T = any>(config: RequestConfig<T>): Promise<T> {
    return new Promise((resolve, reject) => {
      if (config.interceptors?.requestInterceptors) {
        config = config.interceptors.requestInterceptors(config)
      }
      this.instance.request<any, T>(config).then(res => {
        if (config.interceptors?.responseInterceptors) {
          res = config.interceptors.responseInterceptors(res)
        }
        resolve(res)
      }).catch(err => {
        reject(err)
      })
    })
  }

  post<T>(config: RequestConfig<T>): Promise<T> {
    return this.api<T>({ ...config, method: 'POST' })
  }

  get<T>(config?: RequestConfig<T>): Promise<T> {
    return this.api<T>({ ...config, method: "GET" });
  }
}

export default Request